# == Schema Information
#
# Table name: products
#
#  id                  :integer          not null, primary key
#  brand_id            :integer
#  title               :string
#  status              :integer          default("on")
#  uuid                :string
#  msrp                :decimal(10, 2)
#  price               :decimal(10, 2)
#  desc                :text
#  lock_version        :integer
#  created_at          :datetime         not null
#  updated_at          :datetime         not null
#  spec_id             :integer
#  product_sign_id     :integer
#  category_ids        :string           default([]), is an Array
#  summary             :string
#  product_type        :integer          default("finished")
#  sales               :integer          default(0)
#  parent_category_ids :string           default([]), is an Array
#  is_top              :boolean
#

class Product < ApplicationRecord

  include EnumPlus
  include Elasticsearch::Model
  include Elasticsearch::Model::Callbacks
  include Searchable

  enum status: [:on, :off]
  enum product_type: [:finished, :customized]

  validates :category_ids, presence: { message: "分类不能为空" }
  validates :title, presence: { message: "名称不能为空" }
  validates :product_type, inclusion: { in: %w[finished customized],
                                  message: "商品状态必须为finished | customized" }
  validates :status, inclusion: { in: %w[on off],
                                  message: "商品状态必须为on | off" }
  validates :amount, numericality: { only_integer: true,
                                     message: "库存必须为整数" },
                                     if: proc { |product| !product.amount.blank? }
  validates :msrp, presence: { message: "MSRP不能为空" }
  validates :msrp, numericality: { message: "MSRP必须为数字" },
    if: proc { |product| !product.msrp.blank? }
  validates :price, numericality: { message: "价格必须为数字" },
    if: proc { |product| !product.price.blank? }
  validates :price, presence: { message: "价格不能为空" }
  validates :desc, presence: { message: "描述不能为空" }

  belongs_to :spec
  belongs_to :brand
  belongs_to :product_sign

  has_many :images, -> { order(weight: 'desc') }, class_name: 'ProductImage',
    dependent: :destroy
  has_one :main_product_image, -> { order(weight: 'desc') },
    class_name: :ProductImage
  has_one :stock, dependent: :destroy

  has_many :properties, class_name: 'ProductProperty', foreign_key: 'product_id'

  accepts_nested_attributes_for :properties
  accepts_nested_attributes_for :stock

  before_create :set_default_attrs
  before_save :update_parent_category_ids

  delegate :amount, :unit, to: :stock
  delegate :title, to: :brand, prefix: :brand
  delegate :title, to: :spec, prefix: :spec
  #delegate :title, to: :category, prefix: :category
  delegate :content, to: :product_sign, prefix: :product_sign
  delegate :channel_name, to: :brand
  delegate :channel_id, to: :brand

  default_scope { where status: Product.statuses[:on] }

  scope :on_promotion, -> { where('msrp != price') }

  mapping do
    indexes :title, analyzer: 'ik_smart'
    indexes :msrp, type: 'float'
    indexes :sales, type: 'integer'
    indexes :desc, analyzer: 'ik_smart'
    indexes :brand_id
    indexes :category_ids
  end

  def main_img_url
    self.main_product_image.image_url if self.main_product_image.present?
  end

  def product_amount
    self.amount
  end

  def as_json(options={})
    super({methods: [:main_img_url, :product_amount]}.merge(options))
  end

  def category_titles
    Category.where(id: self.category_ids).map(&:title).join(", ")
  end

  def final_summary
    origin = read_attribute(:summary).to_s
    if self.product_sign
      origin + self.product_sign_content.to_s
    else
      origin
    end
  end

  def is_on_promotion?
    self.msrp != self.price
  end

  def get_promotions
    now = Time.now
    Promotion.where("? = ANY(product_ids) and actived = true and started_at <= ? and ended_at > ?", self.id.to_s, now, now)
  end

  class << self

    def get_related_products product_id, category_ids, limit=5
      Product.where("category_ids && ? and id != ?", "{#{category_ids.join(",")}}", product_id).limit(limit)
    end

    def get_floor_products category_id, limit=4
      Product.where("? = ANY(category_ids)", category_id.to_s).limit(limit)
    end

  end

  private

  def set_default_attrs
    self.uuid = RandomCode.generate_product_uuid
  end

  def update_parent_category_ids
    self.parent_category_ids = Category.where(id: self.category_ids).map(&:parent_id).uniq.compact
  end

end
